#ifndef __DISASSEMBLE_H
#define __DISASSEMBLE_H
#include "stdint.h"
#include "global.h"
#include "print.h"
#include "memory.h"
#include "string.h"


// 定义指令的结构体
struct x86_instruction_t{
    uint8_t* start_i;
    uint8_t* i_addr;
    uint8_t prefixes[4];     // 最多4个前缀（REX, Legacy前缀等）
    int prefix_count;        // 前缀数量
    uint8_t vex[3];          // VEX前缀 (2 或 3 字节)
    int vex_length;          // VEX前缀长度 (0表示没有VEX前缀)
    uint8_t opcode[3];       // 主操作码和扩展操作码 (最多3字节)
    int opcode_length;       // 操作码字节数
    uint8_t modrm;           // ModR/M字节
    int has_modrm;           // 是否存在ModR/M字节
    uint8_t modrm_r;         // 存储 ModR/M 字节中的 reg 字段值（可能是操作码扩展或寄存器编号）
    uint8_t sib;             // SIB字节
    int has_sib;             // 是否存在SIB字节
    int displacement;        // 位移值（如果有）
    int displacement_size;   // 位移大小（0, 1, 2, 4 字节）
    int immediate;           // 立即数（如果有）
    int immediate_size;      // 立即数字节数（0, 1, 2, 4, 8 字节）
};

extern bool put_state;
extern struct x86_instruction_t* susceptible_i_tables[0x100];
extern int susceptible_count;
struct x86_ModRM {
    uint8_t mod : 2;  // Mod字段 (高2位)
    uint8_t reg : 3;  // Reg字段 (中间3位)
    uint8_t rm  : 3;  // R/M字段 (低3位)
};

// 函数声明

void x86_instruction_t_init(struct x86_instruction_t* x86_i_t);
void parse_prefix(struct x86_instruction_t* x86_i_t);
void parse_opcode(struct x86_instruction_t* x86_i_t);
void parse_modrm(struct x86_instruction_t* x86_i_t);
void parse_sib(struct x86_instruction_t* x86_i_t);
void parse_displacement(struct x86_instruction_t* x86_i_t);
void parse_immediate(struct x86_instruction_t* x86_i_t);
void x86_disassemble(void* i_addr, void* d_addr);
void x86_dis(struct x86_instruction_t* x86_i_t);

#define MAX_INSTRUCTION_LEN 15 // x86指令最大长度
#define MODRM_R_T 1
#define MODRM_R_F 0
#define HAS_MODRM_T 1
#define HAS_MODRM_F 0
#define HAS_SIB_T 1
#define HAS_SIB_F 0



#define PUSH_EAX 0x50
#define PUSH_EDX 0x52
#define PUSH_EBP 0x55 
#define PUSH_ESI 0x56
#define PUSH_EDI 0x57
#define PUSH_EBX 0x53
#define PUSH_ECX 0x51
#define PUSH_IMM8 0x6a
#define PUSHA_ 0x60
#define PUSH_DS 0x1e
#define PUSH_ES 0x06
#define PUSH_FS 0xa0
#define PUSH_GS 0xa8
#define PUSH_IMM32 0x68

#define POP_EAX 0x58
#define POP_EDX 0x5a
#define POP_ECX 0x59
#define POP_EBX 0x5b
#define POP_ESI 0x5e
#define POP_EDI 0x5f
#define POP_EBP 0x5d
#define POPA_ 0x61
#define POP_RM32 0x8f
#define POP_DS 0x1f
#define POP_ES 0x07
#define POP_FS 0xa1
#define POP_GS 0xa9

#define MOV_RM8_R8 0x88
#define MOV_R8_RM8 0x8a 
#define MOV_RM32_R32 0X89
#define MOV_R32_RM32 0x8b
#define MOV_EAX_MOFFS32 0xa1
#define MOV_MOFFS32_EAX 0xa3
#define MOV_RM32_IMM32 0xc7
#define MOVZX_R32_RM8 0xb6
#define MOVZX_R32_RM16 0xb7
#define MOV_RM8_IMM8 0xc6
#define MOV_EAX_IMM32_ 0xb8
#define MOV_ECX_IMM32 0xb9
#define MOV_EDX_IMM32 0xba
#define MOV_EBX_IMM32 0xbb
#define MOV_EBP_IMM32 0xbd
#define MOV_ESI_IMM32 0xbe
#define MOV_EDI_IMM32 0xbf
#define MOV_AL_IMM8 0xb0
#define MOV_CL_IMM8 0xb1
#define MOV_DL_IMM8 0xb2
#define MOVSX_R32_RM8 0xbe
#define MOV_RM16_SREG 0x8c
#define MOV_SREG_RM16 0x8e
#define MOV_M32_M32 0xa5
#define MOV_MOFFS8_AL 0xa2
#define MOV_AL_MOFFS8 0xa0
#define MOV_BL_IMM8 0xb3
#define MOVSB_ 0xa4
#define MOV_AH_IMM8 0xb4

#define AND_RM32_IB 0x83
#define AND_EAX_IMM32 0x25
#define AND_AL_IMM8 0x24
#define AND_RM32_R32 0x21
#define AND_RM32_R8 0x20
#define AND_R8_RM8 0x22
#define AND_R32_RM32 0x23
#define AND_RM8_IMM8 0x80

#define ADD_RM32_IMM8 0x83
#define ADD_EAX_IMM32 0x05
#define ADD_RM8_IMM8 0x80
#define ADD_RM32_IMM32 0x81
#define ADD_RM32_R32 0x01
#define ADD_R32_RM32 0x03
#define ADD_RM8_R8 0x00
#define ADD_R8_RM8 0x02

#define SUB_RM32_IMM32 0x81
#define SUB_RM32_IMM8 0x83
#define SUB_RM32_R32 0x29
#define SUB_EAX_IMM32 0x2d
#define SUB_R32_RM32 0x2b
#define SUB_AL_IMM8 0x2c
#define SUB_RM8_R8 0x28

#define DIV_RM32 0xf7

#define DEC_EAX 0x48
#define DEC_ECX 0x49
#define DEC_EBX 0x4b 
#define DEC_ESI 0x4e
#define DEC_EDI 0x4f
#define DEC_EDX 0x4a
#define DEC_EBP 0x4d
#define DEC_RM32 0xff
#define DEC_RM8 0xfe

#define XOR_RM32_R32 0x31
#define XOR_RM32_IMM8 0x83
#define XOR_R8_RM8 0x32
#define XOR_RM8_R8 0x30
#define XOR_R32_RM32 0x33
#define XOR_RM8_IMM8 0x80

#define CLI 0xfa
#define STI 0xfb
#define CLD_ 0xfc

#define CALL_RE32 0xe8
#define CALL_RM32 0xff

#define CMP_AL_IMM8 0x3c
#define CMP_RM8_R8 0x38
#define CMP_RM32_R32  0x39
#define CMP_EAX_IMM32 0x3d
#define CMP_RM32_IMM8 0x83
#define CMP_RM8_IMM8 0x80
#define CMP_RM32_IMM32 0x81
#define CMP_R32_RM32 0x3b
#define CMP_R8_RM8 0x3a
#define CMPS_M8_M8 0xa6

#define JNE_REL8 0x75
#define JNE_REL32 0x85
#define JMP_REL8 0xeb
#define JMP_REL32 0xe9
#define JE_REL8 0x74
#define JE_REL32 0x84
#define JLE_REL32 0x8e
#define JLE_REL8 0x7e
#define JL_REL8 0x7c
#define JG_REL8 0x7f
#define JBE_REL8 0x76
#define JBE_REL32 0x86
#define JB_REL8 0x72
#define JB_REL32 0x82
#define JAE_REL8 0x73
#define JAE_REL32 0x83
#define JA_REL8 0x77
#define JA_REL32 0x87
#define JGE_REL8 0x7d
#define JGE_REL32 0x8d
#define JS_REL32 0x88
#define JS_REL8 0x78
#define JNS_REL8 0x79
#define JNS_REL32 0x89
#define LJMP_ 0xff
#define JG_REL32 0x8f

#define SHR_RM32_IMM8 0xc1
#define SHL_RM32_IMM8 0xc1
#define SHLD_RM32_R32_IMM8 0xa4
#define SAR_RM32_1 0xd1
#define SAR_RM32_IMM8 0xc1
#define SHR_RM32_CL 0xd3
#define SHL_RM32_CL 0xd3
#define SHL_RM32_1 0xd1
#define SHRD_RM32_R32_IMM8 0xac

#define OR_RM32_IMM32 0x81
#define OR_RM32_IMM8 0x83
#define OR_RM32_R32 0x09
#define OR_AL_IMM8 0x0c
#define OR_EAX_IMM32 0x0d
#define OR_R8_RM8 0x0a
#define OR_R32_RM32 0x0b
#define OR_RM8_R8 0x08
#define OR_RM8_IMM8 0x80

#define ROR_RM32_IMM8 0xc1

#define TEST_RM32_R32 0X85
#define TEST_RM8_R8 0x84
#define TEST_AL_IMM8 0xa8
#define TEST_RM8_IMM8 0xf6
#define TEST_RM32_IMM32 0xf7
#define TEST_EAX_IMM32 0xa9

#define LEA_R32_M 0x8d

#define INC_EAX 0x40
#define INC_ECX 0x41
#define INC_EDX 0x42
#define INC_EBX 0x43
#define INC_EBP 0x45
#define INC_ESI 0x46
#define INC_EDI 0x47
#define INC_RM32 0xff
#define INC_RM8 0xfe

#define OUT_DX_AL 0xee
#define OUT_IMM8_AL 0xe6
#define OUTS_DX_M32 0x6f
#define OUTSB_ 0x6e

#define IN_AL_DX 0xec
#define INSW_M32_DX 0x6d

#define XCHG_R32_EAX 0x90
#define XCHG_R32_RM32 0x87

#define LIDT_ 0x01
#define LGDT_ 0x01
#define LSS_R32_M16_32 0xb2
#define LSL_R32_R32_M16 0x03
#define BSF_R32_RM32 0xbc
#define BTR_RM32_R32 0xb3
#define BT_RM32_R32 0xa3
#define SETB_RM8 0x92
#define LODS_M8 0xac
#define LODS_M23 0xad
#define STOS_ 0xaa
#define SETAE_RM8 0x93
#define BTS_RM32_R32 0xab

#define POPF_ 0x9d
#define PUSHF_ 0x9c
#define STOSD 0xab
#define IMUL_R32_RM32 0xaf
#define IMUL_R32_RM32_IMM8 0x6b
#define IMUL_RM32 0xf7
#define NOT_RM32 0xf7
#define NOT_RM8 0xf6
#define LOOP_REL8 0xe2
#define SETNE_RM8 0x95
#define SETG_RM8 0x9f
#define MOV_CR3_RM32 0x22
#define MOV_RM32_CR3_ 0x20
#define SETE_RM8 0x94
#define __NOP__ 0x90
#define LEAVE 0xc9
#define RET 0xc3
#define RET_IMM16 0xc2
#define IRET_ 0xcf
#define STD_ 0xfd
#define INT_ 0xcd
#define NEG_RM32 0xf7
#define LTR_RM16 0x00
#define LLDI_RM16 0x00
#define STR_RM16 0x00
#define SBB_RM32_R32 0x19 
#define SCAS_AL_ES_EDI 0xae
#define SETBE_RM8 0x96
#define ADC_RM32_IMM8 0x83
#define FNCLEX_ 0xe2


#define FNINIT_ 0xe3
#define FSTSW_AX_ 0xe0
#define FNSETPM_ 0xe4
#define FWAIT 0x9b
#define FNSAVE_ 0xdd
#define FRSTOR_ 0xdd
#define CLTS_ 0x06

#define INT3 0xcc
#endif